<html>
<head>
<link rel="shortcut icon" href="./favicon.ico">
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="canonical" href="./Register_IO_Single_Ended.html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="An Input/Output Register with extra attributes to make the CAD tool place it in special I/O register locations around the edge of the FPGA, thus reducing skew.  Also has extra debug inputs and outputs for on-chip test logic to avoid disturbing the placement of the I/O register.">
<title>Register IO Single Ended</title>
</head>
<body>

<p class="inline bordered"><b><a href="./Register_IO_Single_Ended.v">Source</a></b></p>
<p class="inline bordered"><b><a href="./legal.html">License</a></b></p>
<p class="inline bordered"><b><a href="./index.html">Index</a></b></p>

<h1>A Single-Ended Input/Output Register</h1>
<p>An Input/Output Register with extra attributes to make the CAD tool
 place it in special I/O register locations around the edge of the FPGA,
 thus reducing skew.  Also has extra debug inputs and outputs for on-chip
 test logic to avoid disturbing the placement of the I/O register.</p>
<h2>Input or Output Usage</h2>
<ul>
<li>For an input I/O: set <code>DIRECTION</code> to <code>"INPUT"</code>, and connect the I/O input
 pin to <code>data_in</code>, and <code>data_out</code> to the receiving logic.</li>
<li>For an output I/O: set <code>DIRECTION</code> to <code>"OUTPUT"</code>, and connect the sending
 logic to <code>data_in</code> and the I/O output pin to <code>data_out</code>.</li>
</ul>
<h2>Debugging Support</h2>
<p>It's likely for the I/O Register to be inside another module and thus
 invisible. Connecting any logic at the same time as the I/O pin to
 <code>data_in</code> or <code>data_out</code> will prevent placing the I/O Register into an I/O
 location since we can only connect one thing at a time to an I/O pin. So we
 provide separate debug signals which do not touch the I/O pin.</p>
<p>The <code>debug_out</code> port mirrors <code>data_out</code> and is usually brought out to the
 ports of the module enclosing the I/O Register, so you don't have to alter
 the module logic to monitor operation. While a given <code>debug_in_enable</code> bit
 is set, then the corresponding <code>debug_in</code> replaces the same <code>data_in</code> bit,
 which allows for injecting test signals without using extra pins.</p>
<h2>Ports and Parameters</h2>

<pre>
`default_nettype none

module <a href="./Register_IO_Single_Ended.html">Register_IO_Single_Ended</a>
#(
    parameter                   WORD_WIDTH  = 0,
    parameter [WORD_WIDTH-1:0]  RESET_VALUE = 0,
    parameter                   DIRECTION   = "" // "INPUT" or "OUTPUT"
)
(
    input   wire                        clock,
    input   wire                        clock_enable,
    input   wire                        clear,

    input   wire    [WORD_WIDTH-1:0]    data_in,
    output  wire    [WORD_WIDTH-1:0]    data_out,

    input   wire    [WORD_WIDTH-1:0]    debug_in,
    input   wire    [WORD_WIDTH-1:0]    debug_in_enable,
    output  wire    [WORD_WIDTH-1:0]    debug_out
);
</pre>

<h2>Registers with attributes</h2>
<p>This module is a specialization of the simple <a href="./Register.html">Synchronous
 Register</a> module, since we must apply the attributes
 directly to the HDL register and not the module as a whole. See the
 Synchronous Register module for further documentation and discussion.</p>
<p>Depending on your CAD tool, optimization passes may or may not remove and
 reconstruct the register and thus lose the attributes specifying placement
 of the register into an I/O buffer location. Also, applying other attributes
 may interfere with I/O buffer placement.</p>
<p>Under Vivado, using a <code>DONT_TOUCH</code> attribute or constraint on this module,
 or the <code>data_reg</code> register, will prevent the <code>IOB</code> attribute from taking
 effect, as it inhibits <em>any</em> optimization, including placement into an IOB
 location. However, we must use a <code>KEEP</code> attribute to prevent optimization
 transformations on this register before placement, as mentioned above.</p>

<pre>
    // Quartus
    (* useioff = 1 *)

    // Vivado
    (* KEEP = "TRUE" *)
    (* IOB  = "TRUE" *)

    reg [WORD_WIDTH-1:0] data_reg = RESET_VALUE;
</pre>

<h2>Clocking and Reset</h2>
<p>Here, we use the  "last assignment wins" idiom (See
 <a href="./verilog.html#resets">Resets</a>) to implement reset.  This is also one
 place where we cannot use ternary operators, else the last assignment for
 clear (e.g.: <code>data_out &lt;= (clear == 1'b1) ? RESET_VALUE : data_out;</code>) would
 override any previous assignment with the current value of <code>data_out</code> if
 <code>clear</code> is not asserted!</p>

<pre>
    wire [WORD_WIDTH-1:0] data_in_internal;

    always @(posedge clock) begin
        if (clock_enable == 1'b1) begin
            data_reg <= data_in_internal;
        end

        if (clear == 1'b1) begin
            data_reg <= RESET_VALUE;
        end
    end
</pre>

<h2>Debug Support</h2>
<p>We also mimic the I/O Register with a conventional register taking a debug
 input. If a <code>debug_in_enable</code> bit is set, then the matching <code>debug_in</code>
 input bit will show up at the same <code>data_out</code> bit and <code>debug_out</code> bit
 outputs instead of <code>data_in</code>, with the same 1-cycle latency.  This enables
 generating signals and testing without having to use extra FPGA pins or
 disturbing the I/O register placement.</p>

<pre>
    reg  [WORD_WIDTH-1:0] debug_in_internal = RESET_VALUE;
    wire [WORD_WIDTH-1:0] debug_in_captured;

    <a href="./Register.html">Register</a>
    #(
        .WORD_WIDTH     (WORD_WIDTH),
        .RESET_VALUE    (RESET_VALUE)
    )
    debug_reg
    (
        .clock          (clock),
        .clock_enable   (clock_enable),
        .clear          (clear),
        .data_in        (debug_in_internal),
        .data_out       (debug_in_captured)
    );
</pre>

<h2>INPUT and OUTPUT logic</h2>
<p>We wire up the debug register and logic as necessary for <code>INPUT</code> or
 <code>OUTPUT</code> operation. The debug logic must never touch the I/O pin.</p>

<pre>
    generate

        // verilator lint_off WIDTH
        if (DIRECTION == "INPUT") begin
        // verilator lint_on  WIDTH

            <a href="./Multiplexer_Bitwise_2to1.html">Multiplexer_Bitwise_2to1</a>
            #(
                .WORD_WIDTH (WORD_WIDTH)
            )
            debug_bit_select
            (
                .bitmask    (debug_in_enable),
                .word_in_0  (data_reg),
                .word_in_1  (debug_in_captured),
                .word_out   (data_out)
            );

            always @(*) begin
                debug_in_internal   = debug_in;
            end

            assign data_in_internal = data_in;
            assign debug_out        = data_out;
        end

        // verilator lint_off WIDTH
        if (DIRECTION == "OUTPUT") begin
        // verilator lint_on  WIDTH

            <a href="./Multiplexer_Bitwise_2to1.html">Multiplexer_Bitwise_2to1</a>
            #(
                .WORD_WIDTH (WORD_WIDTH)
            )
            debug_bit_select
            (
                .bitmask    (debug_in_enable),
                .word_in_0  (data_in),
                .word_in_1  (debug_in),
                .word_out   (data_in_internal)
            );

            always @(*) begin
                debug_in_internal = data_in_internal;
            end

            assign data_out  = data_reg;
            assign debug_out = debug_in_captured;
        end

    endgenerate

endmodule
</pre>

<hr>
<p><a href="./index.html">Back to FPGA Design Elements</a>
<center><a href="https://fpgacpu.ca/">fpgacpu.ca</a></center>
</body>
</html>

